package example.demo.route.spi;

import example.demo.route.routerule.RouteRule;
import example.demo.route.routerule.impl.DefaultRouteRule;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Iterator;
import java.util.ServiceLoader;

/**
 * <? 方式一
 * <p>
 * 完成spi获取对象的注入到bean容器去
 */
//@Component
public class SpiRegisterBean implements BeanFactoryPostProcessor,
        ApplicationContextAware,
        ApplicationListener<ServletWebServerInitializedEvent>,
        /*因为di无效，所以实现这个接口*/
        EnvironmentAware {

    public SpiRegisterBean(ApplicationContext applicationContext) {
        //没有打印
        System.out.println("SpiRegisterBean---//@Component");
    }

    Environment environment;

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Component
    static class SpiBean {

        /**
         * di-succeed
         */
        @Autowired
        public SpiBean(RouteRule routeRule) {
            //打印了
            System.out.println("SpiRegisterBean---//@Component" + routeRule);
        }
    }

    ApplicationContext applicationContext;

    /**
     * <? 先经过spi得到目标对象，再其次加入到spring管理bean的容器【singletonObjects】
     * <? beanFactory.registerSingleton(beanname, bean-obj);是所有加入bean集合必备的一步。
     * 不过这种方式，不要用那些di的注解，因为这个点不进行di。而且di的BeanPostProcessor都还没出来。而且那个di开关也是false。
     * 开关在ConfigurationClassPostProcessor.postProcessBeanFactory-->
     * beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
     * 才将di开关置为true，只要di开关为true，才可进行di
     * <? this.hasInstantiationAwareBeanPostProcessors = true;这个就是di开关
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        ServiceLoader<RouteRule> routeRules = ServiceLoader.load(RouteRule.class);
        Iterator<RouteRule> iterator = routeRules.iterator();
        RouteRule next = iterator.next();
        String property = environment.getProperty("rao.table-sum");
        if (null == property) {
            next.setTableSum(4);
        } else {
            next.setTableSum(Integer.parseInt(property));
        }
        String simpleName = next.getClass().getSimpleName();
        /**<? 将RouteRule加入到spring管理bean的集合去，但不会加入到beanDefinitionNames，看来这种方式不完美*/
        beanFactory.registerSingleton(simpleName.replace(simpleName.charAt(0), (char) (simpleName.charAt(0) + 32)), next);
    }


//    public static void main(String[] args) {
//        String simpleName = DefaultRouteRule.class.getSimpleName();
//        System.out.println(simpleName.replace(simpleName.charAt(0), (char) (simpleName.charAt(0) +32)));
//        System.out.println('A'-'a');
//    }

    @Override
    public void onApplicationEvent(ServletWebServerInitializedEvent event) {
        DefaultRouteRule bean = applicationContext.getBean(DefaultRouteRule.class);
        Arrays.stream(applicationContext.getBeanDefinitionNames()).forEach(System.out::println);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
